package com.example.demo.oauth2;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.demo.bean.User;
import com.example.demo.security.UserServiceImpl;
import com.example.demo.service.UserInfoService;
import com.example.demo.service.UserService;
import com.sun.org.apache.xerces.internal.util.HTTPInputSource;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;

import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 用户登录省份验证：外调新版的认证系统·
 * 
 * @author xiaoyan
 * @version 创建时间：2017年8月7日 上午10:15:40
 *    
 */

@Controller
public class LoginController {


	@Autowired
	private UserService userService;
	@Autowired
	private UserInfoService userInfoService1;

	// 设置应用系统的AppID，每个应用都不同，你要先去申请注册
	private static String appId = "javaee";

	// 设置应用系统的appSecret，每个应用都不同，你要先去申请注册
	private static String appSecret = "b3b52e43ccfd";

	// '中央认证登录页
	private static String CAS_Server = "http://localhost:8080/zhuye";    //要换你自己的
	// -----------
	private static String casLoginUrl = "https://cas.dgut.edu.cn?appid=javaee";   ////要换你自己的

	// '中央认证兑票页
	private static String httpService = "https://cas.dgut.edu.cn/ssoapi/v2/checkToken";    //不用换

	// 获取用户信息
	private static String userInfoService = "https://cas.dgut.edu.cn/oauth/getUserInfo";   //不用换

	private String username1;
	private  AuthenticationManager am = new AuthenticationManager() {
		@Override
		public Authentication authenticate(Authentication authentication) throws AuthenticationException {
			if (authentication.getName().equals(authentication.getCredentials())) {
				            return new UsernamePasswordAuthenticationToken(authentication.getName(), authentication.getCredentials(),null);
				        }
			         // 没有通过认证则抛出密码错误异常
			throw new BadCredentialsException("Bad Credentials");
		}
	};


		/*
		 *
		 * 1 第一步，用户发起登录，获取token
		 * 用户发起用登录，APP端携带appid请求服务端，服务端验证app合法性，app合法性通过后用户输入账号密码提交，中央认证验证合法性后
		 *
		 * 2第二步，通过token获取access_token和openid
		 * -APP端获取到token，利用token、appid和appsecret去获取access_token和openid
		 *
		 * 3第三步，通过access_token和openid获取个人信息
		 */

		@ResponseBody
		@RequestMapping(value = "/login/dgut")
		public void login(HttpServletRequest request, HttpServletResponse response, Model model) throws IOException {
			// 1从中央验证系统获取token
			String token = request.getParameter("token");
			String username = request.getParameter("usrname");
			String password = request.getParameter("password");
			System.out.println("token==============================" + token);
			// 没有Token，把用户重定向到中央认证登陆页
			if (token == null || "".equals(token)) {
				System.out.println("token为空格");
				// 跳到中央登录登录验证系统，这个异常判断
				response.sendRedirect(casLoginUrl);
				System.out.println(token);
			} else {
				// 有票，开始兑票------第二步，通过token获取access_token和openid
				String ip = "172.27.15.28";

				System.out.println("token===" + token);
				String userIp = request.getLocalAddr();
				System.out.println("userIp===" + userIp);
				// 开始访问接口，验证token值

				Map<String, String> userInfo = postToken(token, userIp);

				Authentication request1 = new UsernamePasswordAuthenticationToken(userInfo.get("username"), userInfo.get("username"));
				System.out.println(request1);
				Authentication result = am.authenticate(request1);
				System.out.println(result);
				SecurityContextHolder.getContext().setAuthentication(result);
				if(userService.login(userInfo.get("username")) == null){
					User user = new User(null, userInfo.get("username"), "123456", "学生", 2);
					userService.addUser(user);
					userInfoService1.addUserInfo(userInfo.get("username"), "学生");
				}
				System.out.println("认证成功，Security context 包含：" + SecurityContextHolder.getContext().getAuthentication());
				//UserDetails result=new UserServiceImpl().loadUserByUsername(username1);
				//System.out.println(result);
				response.sendRedirect(CAS_Server);

			}
		}

		/*
		 * 2第二步，通过token获取access_token和openid
		 * -APP端获取到token，利用token、appid和appsecret去获取access_token和openid
		 *
		 * 3第三步，通过access_token和openid获取个人信息
		 */
		private Map<String, String> postToken(String token, String useip) throws ParseException, IOException {
			String myToken = token;
			String url = httpService;
			Map<String, String> userInfo = new HashMap<String, String>();
			//HttpClient httpClient = new DefaultHttpClient();
			HttpClient httpClient = GetHttpClient.getHttpClient();
			String json = jsonMethod(token, useip, "javaee", "b3b52e43ccfd");
			HttpPost post = new HttpPost(url);
			StringEntity postingString = new StringEntity(json);// json传递
			post.setEntity(postingString);
			post.setHeader("Content-type", "application/json");
			HttpResponse response = httpClient.execute(post);
			String content = EntityUtils.toString(response.getEntity());
			if (content != null || "".equals(content)) {
				Map<String, String> map = JSON.parseObject(content, Map.class);
				String openid = map.get("openid");
				String accessToken = map.get("access_token");
				if (openid != null || "".equals(openid)) {
					userInfo = getUserInfo(accessToken, openid);
					System.out.println("userInfo==" + userInfo);
				}
			}
			post.releaseConnection();
			System.out.println("postToken==" + content);
			return userInfo;

		}

		/*
		 * 第三步：通过access_token和openid获取个人信息
		 */
		private Map<String, String> getUserInfo(String aaccessToken, String openid) throws ParseException, IOException {
			Map<String, String> infoMap = new HashMap<String, String>();
			//HttpClient httpClient = new DefaultHttpClient();
			HttpClient httpClient = GetHttpClient.getHttpClient();
			HttpPost post = new HttpPost(userInfoService);
			JSONObject jsonObject = new JSONObject();
			jsonObject.put("access_token", aaccessToken);
			jsonObject.put("openid", openid);
			String jsonstr = JSONObject.toJSONString(jsonObject);
			StringEntity postingString = new StringEntity(jsonstr);// jsonstr传递
			post.setEntity(postingString);
			post.setHeader("Content-type", "application/json");
			HttpResponse response = httpClient.execute(post);
			String content = EntityUtils.toString(response.getEntity());
			System.out.println("getUserInfocontent==" + content);
			if (content != null || "".equals(content)) {
				////获取用户信息
				Map<String, String> map = JSON.parseObject(content, Map.class);
				String username = map.get("username");
				String name = map.get("name");
				String group = map.get("group");
//			BeanUtils.copyProperties(source, target);
				if (username != null || "".equals(username)) {
					infoMap.put("username", username);
					infoMap.put("name", name);
					infoMap.put("group", group);
				}
			}
			post.releaseConnection();
			return infoMap;
		}

		/*
		 * 参数名 是否必须 类型 说明
		 *  token 是 string
		 *  上一步获取的token
		 *  appid 是 string appid appsecret
		 * 是 string app密钥 userip 是 string ip地址
		 */
		public static String jsonMethod(String token, String userip, String appid, String appsecret) {
			System.out.println("userip==" + userip);
			String localIp = "";
			// 当在服务器上本地测试时，用户访问ip会变成10.0.2.2，而中央认证将获取到本地服务器ip，故需要手动替换
			if ("10.0.2.2".equals(userip)) {
				localIp = "172.27.15.28";
			} else {
				localIp = userip;
			}
			JSONObject jsonObject = new JSONObject();
			jsonObject.put("token", token);
			jsonObject.put("appid", appid);
			jsonObject.put("appsecret", appsecret);
			jsonObject.put("userip", localIp);
			String jsonstr = JSONObject.toJSONString(jsonObject);
			System.out.println("jsonMethod的jsonstr+++++====" + jsonstr);
			return jsonstr;
		}

	}

